package structures.lists;

public class SingleLinkedList implements IListStructure {
    
    // The first node
    private ListNode start_node;
    // The last node
    private ListNode last_node;
    
    /**
     * List constructor
     */
    public SingleLinkedList() {
        this.start_node = null;
        this.last_node = null;
    }
    
    /**
     * Gets an object from the list
     * @param index Index of the list where to retrieve the object from
     * @return The object in the specified index, or null if none
     */
    public Object get(int index) {
        int count = 0;
        ListNode iterator = this.start_node;
        
        while(iterator != null && count != index) {
            iterator = iterator.next();
            count++;
        }
        
        if(iterator == null)
            return null;
        
        return iterator.getObject();
    }
    
    /**
     * Sets an object in a specified position of the list
     * @param index The index where to set the object in the list
     * @param obj The object to set in the specified index
     */
    public void set(int index, Object obj) {
        int count = 0;
        ListNode iterator = this.start_node;
        
        while(iterator != null && count != index) {
            iterator = iterator.next();
            count++;
        }
        
        if(iterator != null)
            iterator.setObject(obj);
    }
    
    /**
     * Adds an object to the end of the list
     * @param obj Object to add to the end of the list
     */
    public void add(Object obj) {
        if(this.start_node == null) {
            this.start_node = new ListNode(obj);
        } else {
            if(this.last_node == null) {
                this.last_node = new ListNode(obj);
                this.start_node.setNext(this.last_node);
            } else {
                this.last_node.setNext(new ListNode(obj));
                this.last_node = this.last_node.next();
            }
        }
    }
    
    /**
     * Returns the number of elements in the list
     */
    public int size() {
        int count = 0;
        ListNode iterator = this.start_node;
        
        while(iterator != null) {
            iterator = iterator.next();
            count++;
        }
        
        return count;
    }
    
    /**
     * Removes an object from a specified position in the list
     * @param index Index where to remove the object from
     */
    public void remove(int index) {
        if(index == 0) {
            this.start_node = this.start_node.next();
        } else {
            int count = 0;
            ListNode previous = null;
            ListNode iterator = this.start_node;
            
            
            while(iterator != null && count != index) {
                previous = iterator;
                iterator = iterator.next();
                count++;
            }
            
            if(iterator != null && index > 0)
                previous.setNext(iterator.next());
        }
    }
}
